home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / knowhow4 / s_var.cpp < prev    next >
C/C++ Source or Header  |  1994-10-28  |  9KB  |  328 lines

  1. #include "s_var.h"
  2.  
  3. inline long abs(long x)
  4.     {
  5.     return x<0 ? -x+1 : x;
  6.     }
  7. ////////////////////
  8. Var_Table::Var_Table()
  9.     {
  10.     if((memory = new char[MEMORY_STEP]) == NULL)
  11.     {
  12.     kh_error_code = KH_MEMORY_ERROR;
  13.     memory = NULL;
  14.     adresses = NULL;
  15.     types = NULL;
  16.     return;
  17.     }
  18.     if((adresses = new long[ADRESS_STEP]) == NULL)
  19.     {
  20.     kh_error_code = KH_MEMORY_ERROR;
  21.     delete memory;
  22.     memory = NULL;
  23.     adresses = NULL;
  24.     types = NULL;
  25.     return;
  26.     }
  27.     if((types = new int[ADRESS_STEP]) == NULL)
  28.     {
  29.     kh_error_code = KH_MEMORY_ERROR;
  30.     delete memory;
  31.     delete adresses;
  32.     memory = NULL;
  33.     adresses = NULL;
  34.     types = NULL;
  35.     return;
  36.     }
  37.     memory_size = MEMORY_STEP;
  38.     memory_used = 0;
  39.     size = ADRESS_STEP;
  40.     used = 0;
  41.     marked = 0;
  42.     mem_marked = 0;
  43.  
  44.     memset(memory, 0, memory_size);
  45.     memset(types, FREE, size);
  46.     memset(adresses, 0, P * size); // sizeof POINTER in LARGE model == 4 BYTES
  47.     }
  48. /////////////////////////////////
  49. Var_Table::~Var_Table()
  50.     {
  51.     for(; used > 0; used--)
  52.     {
  53.     delete remove(used - 1, OFF);
  54.     }
  55.     delete memory;
  56.     delete adresses;
  57.     delete types;
  58.     }
  59. /////////////////////////////////
  60. int Var_Table::get_type(int n)
  61.     {
  62.     int t = types[n];
  63.     if(t >= 0)                               // Not pointers
  64.     type = size_of = t;
  65.     else if(t < -USER_TYPE)                  // Array in memory
  66.     { type = t; size_of = -(t + USER_TYPE); }
  67.     else
  68.     { type = P; size_of = t; }              // Array in heap
  69.     if(adresses[n] < 0)
  70.     type = FREE;
  71.     return type;
  72.     }
  73. //////////////////////////////////
  74. int Var_Table::get_size(int n)
  75.     {
  76.     int t = types[n];
  77.     if(t >= 0)                               // Not pointers
  78.     return t;
  79.     else if(t < -USER_TYPE)                  // Array in memory
  80.     return n == used - 1 ? memory_used - abs(adresses[n])
  81.                  : abs(adresses[n + 1]) - abs(adresses[n]);
  82.     else
  83.     return P;                            // Array in heap
  84.     }
  85. //////////////////////////////////
  86. void* Var_Table::remove(int n, bool check)
  87.     {
  88.     if(adresses[n] < 0 || n >= used )
  89.     return NULL;
  90.  
  91.     mem_marked += get_size(n);
  92.     void* ret = NULL;
  93.     if(types[n] > -USER_TYPE && types[n] < 0)         // Pointer to heap
  94.     (long*)ret = (long*)(((long*)(memory + adresses[n]))[0]);
  95.     marked++;
  96.     adresses[n] = -adresses[n] - 1;
  97.  
  98.     if(check)
  99.     check_memory_compress();
  100.  
  101.     return ret;
  102.     }
  103. /////////////////////////////////
  104. long Var_Table::find(int n)
  105.     {
  106.     get_type(n);
  107.     return adresses[n];
  108.     }
  109. /////////////////////////////////
  110. int Var_Table::add(void* v, int t, int n, uint elems)
  111.     {
  112.     long addr;                       // Address of location in memory
  113.     int back = t;                    // Size of type or array
  114.     if(t < -USER_TYPE)
  115.     back = -(t + USER_TYPE) * elems;
  116.     else if(t < 0)
  117.     back = P;
  118.     if(types[n] != t || n == -1       // Incomp. types or add to the end
  119.     || n == used                  // Direct write to the end
  120.     || (t < -USER_TYPE && elems > get_size(n))) // Array
  121.     {
  122.     n = used++;
  123.     addr = memory_used;
  124.     memory_used += back;
  125.     if(!check_memory_expand())    // Not enought memory
  126.         {
  127.         used--;
  128.         memory_used -= back;
  129.         return -1;
  130.         }
  131.     }
  132.     else
  133.     addr = adresses[n];           // Insert, not add
  134.  
  135.     switch(t)
  136.     {
  137.     case C: memory[addr] = ((char*)v)[0]; break;       // char
  138.     case I: ((int*)(memory + addr))[0] = ((int*)v)[0]; break;        // int
  139.     case L: ((long*)(memory + addr))[0] = ((long*)v)[0]; break;       // long
  140.     case D: ((double*)(memory + addr))[0] = ((double*)v)[0]; break;     // double
  141.     case PC: case PI: case PL: case PD:                // Array in memory
  142.         memcpy(memory + addr, (char*)v, back);
  143.         break;
  144.     default:
  145.         ((long*)(memory + addr))[0] = (long)(v);
  146.         break;
  147.     }
  148.     adresses[n] = addr; types[n] = t;
  149.  
  150.     if(n != used - 1 &&  // Array copied over prev. array and free space find
  151.     (t < -USER_TYPE && elems > abs(adresses[n + 1]) - abs(adresses[n])))
  152.     {
  153.     types[used] = t;                                   // Mark-to-remove
  154.     adresses[used++] = (long)(memory + addr + back);
  155.     }
  156.     return n;
  157.     }
  158. /////////////////////////////////
  159. int Var_Table::check_memory_expand()
  160.     {
  161.     int* t = types;
  162.     long* l = adresses;
  163.     char* c = memory;
  164.     if(size <= used)
  165.     {
  166.     if((types = (int*)realloc((int*)types,
  167.         (size = (used / ADRESS_STEP + 1) * ADRESS_STEP) * sizeof(int)))
  168.         == NULL)
  169.         {
  170.         size -= ADRESS_STEP;
  171.         types = t;
  172.         return 0;
  173.         }
  174.     if((adresses = (long*)realloc((long*)adresses,
  175.         size * sizeof(long))) == NULL)
  176.         {
  177.         delete types;
  178.         types = t;
  179.         adresses = l;
  180.         return 0;
  181.         }
  182.     }
  183.     if(memory_size <= memory_used)
  184.     {
  185.     if((memory = (char*)realloc((char*)memory,
  186.         (memory_size = (memory_used / MEMORY_STEP + 1) * MEMORY_STEP)
  187.         * sizeof(char))) == NULL)
  188.         {
  189.         memory = c;
  190.         return 0;
  191.         }
  192.     }
  193.     return 1;
  194.     }
  195. /////////////////////////////
  196. int Var_Table::check_memory_compress()
  197.     {
  198. //    if(used / 2 < marked || memory_used / 2 < mem_marked
  199. //    || used == size || memory_used == memory_size)
  200.     return memory_compress();
  201. //    return 0;
  202.     }
  203. /////////////////////////////
  204. int Var_Table::memory_compress()
  205.     {
  206.     int removed = 0;
  207.     long shift = 0;
  208.     long addr;
  209.     for(int i = 0; i < used; i++)
  210.     {
  211.     if((addr = adresses[i + removed]) < 0)
  212.         addr = -addr - 1;
  213.     addr -= shift;
  214.     while(adresses[i + removed] < 0 && i + removed < used)
  215.         {
  216.         shift += get_size(i + removed);
  217.         removed++;
  218.         }
  219.     if(i + removed == used)
  220.         break;
  221.  
  222.     int sz = get_size(i + removed);
  223.     memmove(memory + addr, memory + addr + shift,  sz);
  224.     int sign = adresses[i + removed] < 0 ? -1 : 1;
  225.     adresses[i] = sign * (abs(adresses[i + removed]) - shift);
  226.     types[i] = types[i + removed];
  227.     }
  228.  
  229.     memory_used -= shift;
  230.     used -= removed;
  231.  
  232.     if(size - used > ADRESS_STEP)
  233.     {
  234.     size = (size / used + 1) * ADRESS_STEP;
  235.     adresses = (long*)realloc((long*)adresses, size * sizeof(long));
  236.     types = (int*)realloc((int*)types, size * sizeof(int));
  237.     }
  238.     marked = 0;
  239.     mem_marked = 0;
  240.     return removed;
  241.     }
  242. /////////////////////////////////// Demo code ///////////////////////////////
  243. #include <iostream.h>
  244. class Demo : public Var_Table
  245.     {
  246.     public:
  247.     void report();
  248.     };
  249.  
  250. void Demo::report()
  251.     {
  252.     cout << "\r\n";
  253.     for(int i = 0; i < used; i++)
  254.     {
  255.     int type = types[i];
  256.     cout << "i: " << i << ", type: ";
  257.     switch(type)
  258.         {
  259.         case C: cout << "C"; break;
  260.         case I: cout << "I"; break;
  261.         case L: cout << "L"; break;
  262.         case D: cout << "D"; break;
  263.         case PC: cout << "PC"; break;
  264.         case PI: cout << "PI"; break;
  265.         case PL: cout << "PL"; break;
  266.         case PD: cout << "PD"; break;
  267.         default: cout << "pointer"; break;
  268.         }
  269.  
  270.     int sz = type > 0 ? type : (type < -USER_TYPE ? -type : P);
  271.     cout << ", (elem.) size: " << sz << ", value: ";
  272.  
  273.     if(adresses[i] < 0)
  274.         cout << "FREE";
  275.     else
  276.         switch(type)
  277.         {
  278.         case C: cout << ((char*)(memory + adresses[i]))[0]; break;
  279.         case I: cout << ((int*)(memory + adresses[i]))[0]; break;
  280.         case L: cout << ((long*)(memory + adresses[i]))[0]; break;
  281.         case D: cout << ((double*)(memory + adresses[i]))[0]; break;
  282.         case PC: cout << memory + adresses[i]; break;
  283.         default: cout << "POINTER";    break;
  284.         }
  285.     cout << "\r\n";
  286.     }
  287.     cout << "---------------------------------------------\r\n";
  288.     cout << "used: " << used << ", mem. used: " << memory_used << "\r\n";
  289.     }
  290.  
  291. void main()
  292.     {
  293.     Demo* v = new Demo();
  294.     char c = 'Y';
  295.  
  296.     int i = 3;
  297.     long l = 12;
  298.     double d = 2.5;
  299.     char* s = strdup("Hello");           // Never use stack strings
  300.     char* pc = "KNOW-HOW.SLANG 5.0";
  301. //         int* pi = &i;      // ERROR! Destructor will call "delete" for i
  302.  
  303. //  >>>>>>>>>    add() check code and alloc/realloc of memory <<<<<<<<<<<<<<<
  304.     v->add(&c, C);                       // char
  305.     v->add(s, -C);                       // char* in heap
  306.     v->add(&i, I);                       // int
  307.     v->add(&l, L);                       // long
  308.     v->add(&d, D);                       // double
  309.     v->add(pc, PC, -1, strlen(pc) + 1);        // Array in memory
  310.     v->report();
  311. //  >>>>>>>>> remove() check code and alloc/realloc of memory <<<<<<<<<<<<<<<
  312.     delete v->remove(0, OFF);             // char, no compress
  313.     v->report();
  314.     delete v->remove(5, OFF);
  315.     v->report();
  316.     delete v->remove(1,OFF);                  // pointer, compress
  317.     v->report();
  318.     v->memory_compress();
  319.     v->report();
  320.     delete v->remove(2);                  // int, compress
  321.     v->report();
  322.     delete v->remove(1);                  // long, compress
  323.     v->report();
  324.  
  325.     delete v;
  326.     }
  327. //////////////////////////// End of Demo code ///////////////////////////////
  328.